home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Storage / LinkMgr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  50.4 KB  |  1,814 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        LinkMgr.cpp
  3.  
  4.     Contains:    Implementation for ODLinkManager class.
  5.  
  6.     Owned by:    Craig Carper
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <6>     9/26/96    CC        1332671: Chain event handlers for Edition
  13.                                     mgr events.
  14.                                     Added RegisterSection, UnregisterSection,
  15.                                     and SectionCreated methods (private).
  16.          <5>     9/13/96    jpa        1386060: Pass ptr to EditionContainerSpec
  17.          <4>     5/24/96    jpa        1246074: SOM_CATCH --> SOM_TRY..SOM_ENDTRY
  18.          <3>     3/26/96    CC        1288720: Removed kODULongSequence value
  19.                                     type.
  20.          <2>     3/15/96    CC        1328345: Extracted code from
  21.                                     GetLinkAEHandler to make GetLink;
  22.                                     Extracted code from RequestLinkAEHandler to
  23.                                     make UseLinkEdition.
  24.  
  25.     To Do:
  26.     In Progress:
  27.         
  28. */
  29.  
  30. #define VARIABLE_MACROS
  31.  
  32. #define ODLinkManager_Class_Source
  33. #include <LinkMgr.xih>
  34.  
  35. #ifndef _EXCEPT_
  36. #include <Except.h>
  37. #endif
  38.  
  39. #ifndef _ODMEMORY_
  40. #include <ODMemory.h>
  41. #endif
  42.  
  43. #ifndef _ISOSTR_
  44. #include <ISOStr.h>
  45. #endif
  46.  
  47. #ifndef _PASCLSTR_
  48. #include <PasclStr.h>
  49. #endif
  50.  
  51. #ifndef SOM_Module_OpenDoc_StdProps_defined
  52. #include <StdProps.xh>
  53. #endif
  54.  
  55. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  56. #include <StdTypes.xh>
  57. #endif
  58.  
  59. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  60. #include <StdDefs.xh>
  61. #endif
  62.  
  63. #ifndef SOM_ODPart_xh
  64. #include <Part.xh>
  65. #endif
  66.  
  67. #ifndef SOM_ODSession_xh
  68. #include <ODSessn.xh>
  69. #endif
  70.  
  71. #ifndef SOM_ODContainer_xh
  72. #include <ODCtr.xh>
  73. #endif
  74.  
  75. #ifndef SOM_ODDocument_xh
  76. #include <Document.xh>
  77. #endif
  78.  
  79. #ifndef SOM_ODDraft_xh
  80. #include <Draft.xh>
  81. #endif
  82.  
  83. #ifndef SOM_ODStorageUnit_xh
  84. #include <StorageU.xh>
  85. #endif
  86.  
  87. #ifndef SOM_ODLink_xh
  88. #include <Link.xh>
  89. #endif
  90.  
  91. #ifndef SOM_ODLinkSource_xh
  92. #include <LinkSrc.xh>
  93. #endif
  94.  
  95. #ifndef SOM_ODLinkSpec_xh
  96. #include <LinkSpec.xh>
  97. #endif
  98.  
  99. #ifndef SOM_ODLinkIterator_xh
  100. #include <LinkItr.xh>
  101. #endif
  102.  
  103. #ifndef SOM_ODLinkSourceIterator_xh
  104. #include <LkSrcItr.xh>
  105. #endif
  106.  
  107. #ifndef _LINKDEFS_
  108. #include <LinkDefs.h>
  109. #endif
  110.  
  111. #ifndef _LINKDLGS_
  112. #include <LinkDlgs.h>
  113. #endif
  114.  
  115. #ifndef _ORDCOLL_
  116. #include <OrdColl.h>
  117. #endif
  118.  
  119. #ifndef _PLFMFILE_
  120. #include <PlfmFile.h>
  121. #endif
  122.  
  123. #ifndef SOM_Module_OpenDoc_Errors_defined
  124. #include <ErrorDef.xh>
  125. #endif
  126.  
  127. #ifndef __ERRORS__
  128. #include <Errors.h>
  129. #endif
  130.  
  131. #ifndef _BARRAY_
  132. #include <BArray.h>
  133. #endif
  134.  
  135. #ifndef _REFCTCOL_
  136. #include "RefCtCol.h"
  137. #endif
  138.  
  139. #ifndef _TEMPOBJ_
  140. #include <TempObj.h>
  141. #endif
  142.  
  143. #ifndef _STORUTIL_
  144. #include <StorUtil.h>
  145. #endif
  146.  
  147. #ifndef _USERSRCM_
  148. #include <UseRsrcM.h>
  149. #endif
  150.  
  151. // For smSystemScript
  152. #ifndef __SCRIPT__
  153. #include <Script.h>
  154. #endif
  155.  
  156. #ifndef __TEXTUTILS__
  157. #include <TextUtils.h>
  158. #endif
  159.  
  160. #ifndef _DLOGUTIL_
  161. #include <DlogUtil.h>
  162. #endif
  163.  
  164. #ifndef _STDTYPIO_
  165. #include <StdTypIO.h>
  166. #endif
  167.  
  168. #ifndef __GESTALT__
  169. #include <Gestalt.h>
  170. #endif
  171.  
  172. #ifndef __TOOLUTILS__
  173. #include <ToolUtils.h>
  174. #endif
  175.  
  176. #ifndef __NOTIFICATION__
  177. #include <Notification.h>
  178. #endif
  179.  
  180. #pragma segment ODLinkManager
  181.  
  182. //==============================================================================
  183. // Constants
  184. //==============================================================================
  185.  
  186. const Boolean kNotSysHandler = false;
  187.  
  188. // Apple event constants
  189. #define kODGetLinkEventID        'gtln'
  190. #define kODRequestLinkEventID    'rqln'
  191. #define keyEditionAlias            'edas'
  192. #define kODLinkSourceKey        'lksr'
  193.  
  194. const    ODUShort    kODStorageUnitRefLen    = 4;
  195. const    ODUShort    kODULongSize            = 4;
  196.  
  197. //==============================================================================
  198. // Local Function Prototypes
  199. //==============================================================================
  200. ODStatic StringPtr BuildErrorString(ODSShort strResourceID, ODError error);
  201.  
  202. ODStatic EditionContainerSpec NewEditionFile(Environment* ev,
  203.             PlatformFile* documentFile,
  204.             ODDraft* draft);
  205.     
  206. ODStatic void EditionFileName(Str255 fileName, ODUShort numb);
  207. ODStatic void TruncateFileName(Str255 fileName, Str63 numberString);
  208.     
  209. ODStatic ODULong NewEditionID(Environment *ev, ODDraft* draft);
  210.     
  211. ODStatic void RemoveEventHandler(AEEventClass theAEEventClass,
  212.                                  AEEventID theAEEventID, 
  213.                                  AEEventHandlerUPP chainedHandler, 
  214.                                  long chainedRefcon);
  215.                                  
  216. ODStatic void RegisterPublishingLinks(Environment *ev, ODDraft* draft);
  217. ODStatic void RegisterSubscribingLinks(Environment *ev, ODDraft* draft);
  218. ODStatic void UpdateEditionFiles(Environment *ev, ODRefCntCollection* collection);
  219. ODStatic void DeleteEditionFiles(Environment *ev, ODRefCntCollection* collection);
  220. ODStatic OSErr GetSectionFromEvent(const AppleEvent* theAppleEvent,
  221.                 SectionHandle* section);
  222. ODStatic void AppendULongToDraftProperty(Environment *ev,
  223.     ODDraft* draft, ODPropertyName prop, ODULong value);
  224. ODStatic ODBoolean SectionIDReserved(Environment *ev,
  225.     ODDraft* draft, ODULong requestedID);
  226. ODStatic ODULong PeekNextGlobalID(Environment *ev,
  227.     ODDraft* draft,
  228.     ODPropertyName globalProp);
  229. ODStatic ODULong ReserveGlobalID(Environment *ev,
  230.     ODDraft* draft,
  231.     ODPropertyName globalProp);
  232.  
  233. ODStatic OSErr ODPascal GetLinkAEHandler(
  234.                             const AppleEvent* theAppleEvent,
  235.                             AppleEvent* reply,
  236.                             long refCon);
  237. ODStatic OSErr ODPascal RequestLinkAEHandler(
  238.                             const AppleEvent* theAppleEvent,
  239.                             AppleEvent* reply,
  240.                             long refCon);
  241. ODStatic OSErr ODPascal SectionReadAEHandler(
  242.                             const AppleEvent* theAppleEvent,
  243.                             const AppleEvent* reply,
  244.                             long refCon);
  245. ODStatic OSErr ODPascal SectionWriteAEHandler(
  246.                             const AppleEvent* theAppleEvent,
  247.                             const AppleEvent* reply,
  248.                             long refCon);
  249. ODStatic OSErr ODPascal SectionScrollAEHandler(
  250.                             const AppleEvent* theAppleEvent,
  251.                             const AppleEvent* reply,
  252.                             long refCon);
  253.  
  254.  
  255. //==============================================================================
  256. // struct DraftInfo
  257. //==============================================================================
  258.  
  259. struct DraftInfo
  260. {
  261.     ODDraft*              draft;
  262.     ODRefCntCollection*    linksToExport;
  263.     ODRefCntCollection*    linksToDelete;
  264.     ODRefCntCollection*    newExportedLinks;
  265.     ODBoolean            linksImported;
  266. };
  267.  
  268. // ODObjectCollection is replaced by ODObjectOrdColl in RefCtCol.h in Utilities
  269.  
  270. //==============================================================================
  271. // class ODObjectCollection
  272. //==============================================================================
  273. // 
  274. // class ODObjectCollection : public OrderedCollection
  275. // {
  276. //     public:
  277. //         ODObjectCollection() : OrderedCollection()    {}
  278. //         ODVMethod ~ODObjectCollection()                {}
  279. // 
  280. //         ODMethod ODBoolean ElementsMatch(ElementType v1,ElementType v2) const;
  281. // };
  282.  
  283. //------------------------------------------------------------------------------
  284. // ODObjectCollection::ElementsMatch (OVERRIDE)
  285. //------------------------------------------------------------------------------
  286.  
  287. // ODBoolean ODObjectCollection::ElementsMatch(ElementType v1,ElementType v2) const
  288. // {
  289. //     Environment* ev = somGetGlobalEnvironment();
  290. //     return ODObjectsAreEqual(ev, (ODObject*) v1, (ODObject*) v2);
  291. // }
  292.  
  293. //==============================================================================
  294. // Static functions
  295. //==============================================================================
  296.  
  297. //------------------------------------------------------------------------------
  298. // LinkMgrNMResponse
  299. //------------------------------------------------------------------------------
  300.  
  301. ODStatic void ODPascal LinkMgrNMResponse(NMRecPtr theNMRecPtr)
  302. {
  303.     OSErr error = NMRemove(theNMRecPtr);
  304. }
  305.  
  306. //==============================================================================
  307. // class ODLinkManager
  308. //==============================================================================
  309.  
  310. //------------------------------------------------------------------------------
  311. // ODLinkManager::InitLinkManager
  312. //------------------------------------------------------------------------------
  313.  
  314. SOM_Scope void  SOMLINK ODLinkManagerInitLinkManager(ODLinkManager *somSelf, Environment *ev,
  315.         ODSession* session)
  316. {
  317.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  318.     ODLinkManagerMethodDebug("ODLinkManager","InitLinkManager");
  319.  
  320.     SOM_TRY
  321.  
  322.     /* Moved from somInit. SOM itself sets fields to zero
  323.     _fSuspendedUpdateLinks = (ODRefCntCollection*) kODNULL;
  324.     _fDraftInfos = (OrderedCollection*) kODNULL;
  325.     _fNMResponseUPP = (NMUPP) kODNULL;
  326.     _fNMRecPtr = (NMRecPtr) kODNULL;
  327.     _fRegisteredSections = (OrderedCollection*) kODNULL;
  328.     _fChainedSectionReadAEHandler = (AEEventHandlerUPP) kODNULL;
  329.     _fChainedSectionWriteAEHandler = (AEEventHandlerUPP) kODNULL;
  330.     _fChainedSectionScrollAEHandler = (AEEventHandlerUPP) kODNULL;
  331.     */
  332.     somSelf->InitObject(ev);
  333.     
  334.     long  gestaltResult;
  335.     OSErr result;
  336.  
  337.     // Check if the Edition manager is present
  338.     result = Gestalt(gestaltEditionMgrAttr, &gestaltResult);
  339.     THROW_IF_ERROR (result, "Error from Gestalt");
  340.  
  341.     // The mysterious 31 is the bit position as BitTst uses a convention opposite to MC68000
  342.     if ( BitTst(&gestaltResult, (31 - gestaltEditionMgrPresent)) == false )
  343.         THROW(kODErrNoEditionManager);
  344.  
  345.     InitLinkDialogs(session);
  346.  
  347.     _fSuspendedUpdateLinks = new ODRefCntCollection(ev);
  348.     _fDraftInfos = new OrderedCollection;
  349.     _fRegisteredSections = new OrderedCollection;
  350.     _fNMResponseUPP = NewNMProc(LinkMgrNMResponse);
  351.     _fNMRecPtr = (NMRecPtr) ODNewPtr(sizeof(NMRec));
  352.     THROW_IF_NULL(_fNMRecPtr);
  353.     _fNMRecPtr->nmStr = kODNULL;    
  354.  
  355.     AEEventHandlerUPP theHandlerUPP ;
  356.     theHandlerUPP = NewAEEventHandlerProc( GetLinkAEHandler ) ;
  357.     THROW_IF_ERROR(AEInstallEventHandler(kODShellSignature,
  358.             kODGetLinkEventID, theHandlerUPP, (long)somSelf, kNotSysHandler));
  359.  
  360.     theHandlerUPP = NewAEEventHandlerProc( RequestLinkAEHandler ) ;
  361.     THROW_IF_ERROR(AEInstallEventHandler(kODShellSignature,
  362.             kODRequestLinkEventID, theHandlerUPP, (long)somSelf, kNotSysHandler));
  363.  
  364.     // Save any Edition mgr event handlers installed by the application or shell
  365.     AEGetEventHandler(sectionEventMsgClass, sectionReadMsgID,
  366.             &_fChainedSectionReadAEHandler, &_fChainedSectionReadRefcon, kNotSysHandler);
  367.     AEGetEventHandler(sectionEventMsgClass, sectionWriteMsgID,
  368.             &_fChainedSectionWriteAEHandler, &_fChainedSectionWriteRefcon, kNotSysHandler);
  369.     AEGetEventHandler(sectionEventMsgClass, sectionScrollMsgID,
  370.             &_fChainedSectionScrollAEHandler, &_fChainedSectionScrollRefcon, kNotSysHandler);
  371.     
  372.     theHandlerUPP = NewAEEventHandlerProc( SectionReadAEHandler ) ;
  373.     THROW_IF_ERROR(AEInstallEventHandler(sectionEventMsgClass, sectionReadMsgID,
  374.             theHandlerUPP, (long)somSelf, kNotSysHandler));
  375.  
  376.     theHandlerUPP = NewAEEventHandlerProc( SectionWriteAEHandler );
  377.     THROW_IF_ERROR(AEInstallEventHandler(sectionEventMsgClass, sectionWriteMsgID,
  378.             theHandlerUPP, (long)somSelf, kNotSysHandler));
  379.  
  380.     theHandlerUPP = NewAEEventHandlerProc( SectionScrollAEHandler );
  381.     THROW_IF_ERROR(AEInstallEventHandler(sectionEventMsgClass, sectionScrollMsgID,
  382.             theHandlerUPP, (long)somSelf, kNotSysHandler));
  383.  
  384.     SOM_CATCH_ALL
  385.     SOM_ENDTRY
  386. }
  387.  
  388. //------------------------------------------------------------------------------
  389. // ODLinkManager::NewSectionID
  390. //------------------------------------------------------------------------------
  391.  
  392. SOM_Scope ODULong  SOMLINK ODLinkManagerNewSectionID(ODLinkManager *somSelf, Environment *ev,
  393.         ODDraft* draft)
  394. {
  395.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  396.     ODLinkManagerMethodDebug("ODLinkManager","NewSectionID");
  397.  
  398.     ODULong sectionID;
  399.  
  400.     SOM_TRY
  401.  
  402.     do 
  403.         sectionID = ReserveGlobalID(ev, draft, kODPropSectionID);
  404.     while
  405.         ( SectionIDReserved(ev, draft, sectionID) );
  406.         
  407.     return sectionID;
  408.  
  409.     SOM_CATCH_ALL
  410.     SOM_ENDTRY
  411.     return 0;
  412. }
  413.  
  414. //------------------------------------------------------------------------------
  415. // ODLinkManager::ReserveSectionID
  416. //------------------------------------------------------------------------------
  417.  
  418. SOM_Scope ODBoolean  SOMLINK ODLinkManagerReserveSectionID(ODLinkManager *somSelf, Environment *ev,
  419.         ODULong sectionID,
  420.         ODDraft* draft)
  421. {
  422.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  423.     ODLinkManagerMethodDebug("ODLinkManager","ReserveSectionID");
  424.  
  425.     SOM_TRY
  426.  
  427.     ODBoolean result = kODFalse;
  428.     
  429.     if ( sectionID >= PeekNextGlobalID(ev, draft, kODPropSectionID) )
  430.         if ( !SectionIDReserved(ev, draft, sectionID) )
  431.         {
  432.             AppendULongToDraftProperty(ev, draft, kODPropReservedSectionIDs, sectionID);
  433.             result = kODTrue;
  434.         }
  435.  
  436.     return result;
  437.  
  438.     SOM_CATCH_ALL
  439.     SOM_ENDTRY
  440.     return kODFalse;
  441. }
  442.  
  443. //------------------------------------------------------------------------------
  444. // ODLinkManager::SectionCreated
  445. //------------------------------------------------------------------------------
  446.  
  447. SOM_Scope void  SOMLINK ODLinkManagerSectionCreated(ODLinkManager *somSelf, Environment *ev,
  448.         SectionHandle section)
  449. {
  450.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  451.     ODLinkManagerMethodDebug("ODLinkManager","SectionCreated");
  452.  
  453.  
  454.     SOM_TRY
  455.  
  456.         if ( IsRegisteredSection(section) == noErr )
  457.         {
  458.             // New sections are registered implicitly, so just add to the
  459.             // list of OpenDoc sections.
  460.             _fRegisteredSections->AddLast(section);
  461.         }
  462.  
  463.     SOM_CATCH_ALL_ENDTRY
  464. }
  465.  
  466. //------------------------------------------------------------------------------
  467. // ODLinkManager::RegisterSection
  468. //------------------------------------------------------------------------------
  469.  
  470. SOM_Scope OSErr  SOMLINK ODLinkManagerRegisterSection(ODLinkManager *somSelf, Environment *ev,
  471.         SectionHandle section,
  472.         ODDraft* draft,
  473.         ODBoolean* aliasWasUpdated)
  474. {
  475.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  476.     ODLinkManagerMethodDebug("ODLinkManager","RegisterSection");
  477.  
  478.     OSErr error = noErr;    ODVolatile(error);
  479.     *aliasWasUpdated = kODFalse;
  480.  
  481.     SOM_TRY
  482.  
  483.         if ( IsRegisteredSection(section) != noErr )
  484.         {
  485.             ODContainer* container = draft->GetDocument(ev)->GetContainer(ev);;
  486.             ODFileSpec documentSpec = GetODFileSpecFromContainer(ev, container);
  487.  
  488.             // Must return the error from RegisterSection.  Note that even if
  489.             // a non-zero error is returned, the section may still be registered.
  490.             // Note: This is the toolbox routine RegisterSection, not a method call!
  491.             error = RegisterSection(&documentSpec, section, aliasWasUpdated);
  492.  
  493.             if ( IsRegisteredSection(section) == noErr )
  494.                 _fRegisteredSections->AddLast(section);
  495.         }
  496.  
  497.     SOM_CATCH_ALL_ENDTRY
  498.  
  499.     return error;
  500. }
  501.  
  502. //------------------------------------------------------------------------------
  503. // ODLinkManager::UnregisterSection
  504. //------------------------------------------------------------------------------
  505.  
  506. SOM_Scope OSErr  SOMLINK ODLinkManagerUnregisterSection(ODLinkManager *somSelf, Environment *ev,
  507.         SectionHandle section)
  508. {
  509.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  510.     ODLinkManagerMethodDebug("ODLinkManager","UnregisterSection");
  511.  
  512.     OSErr error = noErr;
  513.  
  514.     // SOM_TRY
  515.  
  516.         if ( IsRegisteredSection(section) == noErr )
  517.             error = UnRegisterSection(section);
  518.  
  519.         _fRegisteredSections->Remove(section);
  520.  
  521.     // SOM_CATCH_ALL_ENDTRY
  522.  
  523.     return error;
  524. }
  525.  
  526. //-------------------------------------------------------------------------------------
  527. // ODLinkManager: ShowLinkUpdateAlert
  528. //-------------------------------------------------------------------------------------
  529.  
  530. SOM_Scope ODLinkUpdateResult  SOMLINK ODLinkManagerShowLinkUpdateAlert(ODLinkManager *somSelf, Environment *ev,
  531.         ODBaseLinkSource* link)
  532. {
  533.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  534.     ODLinkManagerMethodDebug("ODLinkManager","ShowLinkUpdateAlert");
  535.     
  536.     ODLinkUpdateResult result = kODLinkUpdateContinue; ODVolatile(result);
  537.  
  538.     SOM_TRY
  539.     
  540.         // When we leave the background, iterate over all the link sources
  541.         // that attempted to call ShowLinkUpdateAlert() in the background,
  542.         // showing the alert now and calling the links back with the
  543.         // resulting information.
  544.         
  545.         if ( _fInBackground )
  546.         {
  547.             result = kODLinkUpdateStop;
  548.             if ( !_fSuspendedUpdateLinks->Contains(link) )
  549.                 _fSuspendedUpdateLinks->AddLastAndAcquire(link);
  550.             result = kODLinkUpdateSuspend;
  551.         }
  552.         else
  553.         {
  554.             result = ( ::ShowLinkUpdateAlert() )? 
  555.                 kODLinkUpdateContinue : kODLinkUpdateStop;
  556.         }
  557.  
  558.     SOM_CATCH_ALL
  559.     
  560.     SOM_ENDTRY
  561.     
  562.     return result;
  563. }
  564.  
  565. //-------------------------------------------------------------------------------------
  566. // ODLinkManager: SuspendResume
  567. //-------------------------------------------------------------------------------------
  568.  
  569. #if ODDebug
  570. extern int gODButtonKeyNoEnterOkay;
  571. #endif
  572.  
  573. SOM_Scope void  SOMLINK ODLinkManagerSuspendResume(ODLinkManager *somSelf, Environment *ev,
  574.         ODEventData* event)
  575. {
  576.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  577.     ODLinkManagerMethodDebug("ODLinkManager","SuspendResume");
  578.  
  579.     const short kResumeMask = 0x01;    // High byte suspend/resume event 
  580.  
  581.     ODBoolean inBackground = (event->message & kResumeMask) == 0;
  582.     _fInBackground = inBackground;
  583.  
  584.     SOM_TRY
  585.     
  586.         // When we leave the background, show the alert and iterate over all the
  587.         // link sources that attempted to call ShowLinkUpdateAlert() in the 
  588.         // background, calling the links back with the resulting alert information.
  589.         
  590.         if ( !inBackground )
  591.         {
  592.             ODBaseLinkSource* link = (ODBaseLinkSource*) _fSuspendedUpdateLinks->RemoveFirst();
  593.             if (link)
  594.             {
  595.  
  596.                 ODLinkUpdateResult result = ( ::ShowLinkUpdateAlert() )? 
  597.                     kODLinkUpdateContinue : kODLinkUpdateStop;
  598.  
  599.                 while ( link )
  600.                 {
  601.                     TempODRefCntObject tempLink = link; // ensure it is released
  602.                     
  603.                     // Ignore errors returned by LinkUpdateAlertCompleted
  604.                     TRY
  605.                         link->LinkUpdateAlertCompleted(ev, result);
  606.                     CATCH_ALL
  607.                     ENDTRY
  608.                     
  609.                     link = (ODBaseLinkSource*) _fSuspendedUpdateLinks->RemoveFirst();
  610.                 }
  611.             }
  612.         }
  613.  
  614.     SOM_CATCH_ALL
  615.     
  616.     SOM_ENDTRY
  617. }
  618.  
  619. //------------------------------------------------------------------------------
  620. // ODLinkManager::UnsavedExportedLinks
  621. //------------------------------------------------------------------------------
  622.  
  623. SOM_Scope ODBoolean  SOMLINK ODLinkManagerUnsavedExportedLinks(ODLinkManager *somSelf, Environment *ev,
  624.         ODDraft* draft)
  625. {
  626.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  627.     ODLinkManagerMethodDebug("ODLinkManager","UnsavedExportedLinks");
  628.  
  629.     SOM_TRY
  630.  
  631.     DraftInfo* info = somSelf->GetDraftInfo(ev, draft);
  632.  
  633.     if ( info != (DraftInfo*) kODNULL ) 
  634.     {
  635.         return info->newExportedLinks->Count() > 0;
  636.     }
  637.     else
  638.         return kODFalse;
  639.  
  640.     SOM_CATCH_ALL
  641.     SOM_ENDTRY
  642.     return kODFalse;
  643. }
  644.  
  645. //------------------------------------------------------------------------------
  646. // ODLinkManager::AnyLinkImported
  647. //------------------------------------------------------------------------------
  648.  
  649. SOM_Scope ODBoolean  SOMLINK ODLinkManagerAnyLinkImported(ODLinkManager *somSelf, Environment *ev,
  650.         ODDraft* draft)
  651. {
  652.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  653.     ODLinkManagerMethodDebug("ODLinkManager","AnyLinkImported");
  654.  
  655.     SOM_TRY
  656.  
  657.     DraftInfo* info = somSelf->GetDraftInfo(ev, draft);
  658.  
  659.     if ( info != (DraftInfo*) kODNULL ) 
  660.     {
  661.         return info->linksImported;
  662.     }
  663.     else
  664.         return kODFalse;
  665.  
  666.     SOM_CATCH_ALL
  667.     SOM_ENDTRY
  668.     return kODFalse;
  669. }
  670.  
  671. //------------------------------------------------------------------------------
  672. // ODLinkManager::DraftOpened
  673. //------------------------------------------------------------------------------
  674.  
  675. SOM_Scope void  SOMLINK ODLinkManagerDraftOpened(ODLinkManager *somSelf, Environment *ev,
  676.         ODDraft* draft)
  677. {
  678.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  679.     ODLinkManagerMethodDebug("ODLinkManager","DraftOpened");
  680.  
  681.     SOM_TRY
  682.  
  683.     DraftInfo* info = somSelf->GetDraftInfo(ev, draft);
  684.     
  685.     if ( info == (DraftInfo*) kODNULL ) 
  686.     {
  687.         somSelf->NewDraftInfo(ev, draft);
  688.         RegisterSubscribingLinks(ev, draft);
  689.         RegisterPublishingLinks(ev, draft);
  690.     }
  691.  
  692.     SOM_CATCH_ALL
  693.     SOM_ENDTRY
  694. }
  695.  
  696. //------------------------------------------------------------------------------
  697. // ODLinkManager::DraftSaved
  698. //------------------------------------------------------------------------------
  699.  
  700. SOM_Scope void  SOMLINK ODLinkManagerDraftSaved(ODLinkManager *somSelf, Environment *ev,
  701.         ODDraft* draft)
  702. {
  703.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  704.     ODLinkManagerMethodDebug("ODLinkManager","DraftSaved");
  705.  
  706.     SOM_TRY
  707.  
  708.     DraftInfo* info = somSelf->GetDraftInfo(ev, draft);
  709.     
  710.     if ( info != (DraftInfo*) kODNULL ) 
  711.     {
  712.         UpdateEditionFiles(ev, info->linksToExport);
  713.         info->linksToExport->RemoveAndReleaseAll();
  714.  
  715.         DeleteEditionFiles(ev, info->linksToDelete);
  716.         info->linksToDelete->RemoveAndReleaseAll();
  717.  
  718.         info->newExportedLinks->RemoveAndReleaseAll();
  719.         
  720.         info->linksImported = kODFalse;
  721.     }
  722.     else 
  723.     {
  724.         WARN("Draft is not opened yet.");
  725.     }
  726.  
  727.     SOM_CATCH_ALL
  728.     SOM_ENDTRY
  729. }
  730.  
  731. //------------------------------------------------------------------------------
  732. // ODLinkManager::DraftClosing
  733. //------------------------------------------------------------------------------
  734.  
  735. SOM_Scope void  SOMLINK ODLinkManagerDraftClosing(ODLinkManager *somSelf, Environment *ev,
  736.         ODDraft* draft)
  737. {
  738.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  739.     ODLinkManagerMethodDebug("ODLinkManager","DraftClosing");
  740.  
  741.     SOM_TRY
  742.  
  743.     DraftInfo* info = somSelf->GetDraftInfo(ev, draft);
  744.  
  745.     if ( info != (DraftInfo*) kODNULL ) 
  746.     {
  747.         ODDeleteObject(info->linksToExport); // calls RemoveAndReleaseAll()
  748.  
  749.         ODDeleteObject(info->linksToDelete); // calls RemoveAndReleaseAll()
  750.  
  751.         DeleteEditionFiles(ev, info->newExportedLinks);
  752.         ODDeleteObject(info->newExportedLinks); // calls RemoveAndReleaseAll()
  753.  
  754.         _fDraftInfos->Remove(info);
  755.         delete info;
  756.     }
  757.  
  758.     SOM_CATCH_ALL
  759.     SOM_ENDTRY
  760. }
  761.  
  762. //------------------------------------------------------------------------------
  763. // ODLinkManager::ExportOnSave
  764. //------------------------------------------------------------------------------
  765.  
  766. SOM_Scope ODBoolean  SOMLINK ODLinkManagerExportOnSave(ODLinkManager *somSelf, Environment *ev,
  767.         ODLink* link,
  768.         ODBoolean doExport)
  769. {
  770.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  771.     ODLinkManagerMethodDebug("ODLinkManager","ExportOnSave");
  772.  
  773.     ODBoolean wereToExport = kODFalse;
  774.  
  775.     SOM_TRY
  776.  
  777.     DraftInfo* info = somSelf->GetDraftInfo(ev, link->GetStorageUnit(ev)->GetDraft(ev));
  778.     if ( info != (DraftInfo*) kODNULL ) 
  779.     {
  780.         wereToExport = info->linksToExport->Contains(link);
  781.         if ( wereToExport && !doExport ) 
  782.         {
  783.             info->linksToExport->RemoveAndRelease(link);
  784.             // link->Release(ev);
  785.         }
  786.         else if ( !wereToExport && doExport ) 
  787.         {
  788.             info->linksToExport->AddLastAndAcquire(link);
  789.             // link->Acquire(ev);
  790.         }
  791.     }
  792.  
  793.     return wereToExport;
  794.  
  795.     SOM_CATCH_ALL
  796.     SOM_ENDTRY
  797.     return kODFalse;
  798. }
  799.  
  800. //------------------------------------------------------------------------------
  801. // ODLinkManager::DeleteOnSave
  802. //------------------------------------------------------------------------------
  803.  
  804. SOM_Scope ODBoolean  SOMLINK ODLinkManagerDeleteOnSave(ODLinkManager *somSelf, Environment *ev,
  805.         ODLink* link,
  806.         ODBoolean doDelete)
  807. {
  808.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  809.     ODLinkManagerMethodDebug("ODLinkManager","DeleteOnSave");
  810.  
  811.     ODBoolean wereToDelete = kODFalse;
  812.  
  813.     SOM_TRY
  814.  
  815.     DraftInfo* info = somSelf->GetDraftInfo(ev, link->GetStorageUnit(ev)->GetDraft(ev));
  816.     if ( info != (DraftInfo*) kODNULL ) 
  817.     {
  818.         wereToDelete = info->linksToDelete->Contains(link);
  819.         if ( wereToDelete && !doDelete ) 
  820.         {
  821.             info->linksToDelete->RemoveAndRelease(link);
  822.             // link->Release(ev);
  823.         }
  824.         else if ( !wereToDelete && doDelete )
  825.         {
  826.             info->linksToDelete->AddLastAndAcquire(link);
  827.             // link->Acquire(ev);
  828.         }
  829.     }
  830.  
  831.     return wereToDelete;
  832.  
  833.     SOM_CATCH_ALL
  834.     SOM_ENDTRY
  835.     return kODFalse;
  836. }
  837.  
  838. //------------------------------------------------------------------------------
  839. // ODLinkManager::CreateLink
  840. //------------------------------------------------------------------------------
  841.  
  842. SOM_Scope ODLinkSource*  SOMLINK ODLinkManagerCreateLink(ODLinkManager *somSelf, Environment *ev,
  843.         ODDraft* draft,
  844.         ODLinkSpec* linkSpec)
  845. {
  846.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  847.     ODLinkManagerMethodDebug("ODLinkManager","CreateLink");
  848.  
  849.     ODLinkSource*            linkSource = kODNULL;    ODVolatile(linkSource);
  850.     AppleEvent                theAppleEvent, replyAppleEvent;
  851.     AEAddressDesc            targetAddress;
  852.     OSErr                    error;
  853.     ProcessSerialNumber     psn;
  854.     ProcessSerialNumber     psnLinkSource;
  855.     ODBoolean                isSamePSN;
  856.  
  857.     SOM_TRY
  858.  
  859.         // Create a link source to return
  860.         linkSource = draft->CreateLinkSource(ev, (ODPart*) kODNULL);
  861.  
  862.         // If the draft was created by this process, call the part directly
  863.         GetCurrentProcess(&psn);
  864.         linkSpec->GetOriginatingProcessID(ev, &psnLinkSource);
  865.         SameProcess(&psn, &psnLinkSource, &isSamePSN);
  866.         if ( isSamePSN )
  867.         {
  868.             TempODByteArrayStruct aliasBA;
  869.             somSelf->GetLink(ev, linkSpec, (ODByteArray*) aliasBA);
  870.             somSelf->UseLinkEdition(ev, linkSource, (ODByteArray*) aliasBA);
  871.         }
  872.         else
  873.         {
  874.             // Send an Apple Event to this process specifying a process number
  875.             // address, so the event is delivered as a high-level event
  876.             error = AECreateDesc(typeProcessSerialNumber, &psn,
  877.                                 sizeof(ProcessSerialNumber), &targetAddress);
  878.             THROW_IF_ERROR(error);
  879.             TempAEDesc tmpTargetAddress(&targetAddress);
  880.     
  881.             error = AECreateAppleEvent(kODShellSignature, kODRequestLinkEventID, 
  882.                                 &targetAddress, kAutoGenerateReturnID, 
  883.                                 kAnyTransactionID, &theAppleEvent);
  884.             THROW_IF_ERROR(error);
  885.             TempAEDesc tmpAppleEvent(&theAppleEvent);
  886.         
  887.             // Add the link spec to the Apple event
  888.             linkSpec->WriteToAppleEvent(ev, &theAppleEvent);
  889.             
  890.             // Add the source link to the Apple event
  891.             error = AEPutParamPtr(&theAppleEvent, kODLinkSourceKey, typeLongInteger,
  892.                                 &linkSource, sizeof(linkSource));
  893.             THROW_IF_ERROR(error);
  894.         
  895.             error = AESend(&theAppleEvent, &replyAppleEvent, kAENoReply | kAENeverInteract,
  896.                                 kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  897.             THROW_IF_ERROR(error);
  898.         }
  899.  
  900.     SOM_CATCH_ALL
  901.     
  902.         ODSafeReleaseObject(linkSource);
  903.         linkSource = kODNULL;
  904.  
  905.     SOM_ENDTRY
  906.  
  907.     return linkSource;
  908. }
  909.  
  910. //------------------------------------------------------------------------------
  911. // GetLinkAEHandler
  912. //------------------------------------------------------------------------------
  913.  
  914. ODStatic OSErr ODPascal GetLinkAEHandler(
  915.         const AppleEvent* theAppleEvent,
  916.         AppleEvent* reply,
  917.         long refCon)
  918. {
  919.     ODLinkManager*        somSelf = (ODLinkManager*) refCon;
  920.     Environment*        ev = somGetGlobalEnvironment ();
  921.     ODLinkSpec*            linkSpec = (ODLinkSpec*) kODNULL; ODVolatile(linkSpec);
  922.     OSErr                error = noErr;
  923.  
  924. #if ODDebug
  925.     somPrintf("ODLinkManager: Get Link event received\n");
  926. #endif
  927.  
  928.     TRY
  929.         linkSpec = new ODLinkSpec;    // Can't use factory method; no draft object!
  930.         THROW_IF_NULL(linkSpec, kODErrOutOfMemory);
  931.         linkSpec->ReadFromAppleEvent(ev, (AppleEvent*) theAppleEvent);
  932.  
  933.         TempODByteArrayStruct aliasBA;
  934.         somSelf->GetLink(ev, linkSpec, (ODByteArray*) aliasBA);
  935.  
  936.         error = AEPutParamPtr(reply, keyEditionAlias, typeAlias,
  937.                             aliasBA->_buffer, aliasBA->_length);
  938.     CATCH_ALL
  939.         // Must catch any exceptions thrown!
  940.         error = ErrorCode();
  941.     ENDTRY
  942.  
  943.     delete linkSpec;
  944.     
  945.     return error;
  946. }
  947.  
  948. //------------------------------------------------------------------------------
  949. // GetLink
  950. //------------------------------------------------------------------------------
  951.  
  952. SOM_Scope void SOMLINK ODLinkManagerGetLink(ODLinkManager *somSelf, Environment *ev,
  953.         ODLinkSpec* linkSpec,
  954.         ODByteArray* aliasData)
  955. {
  956.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  957.     ODLinkManagerMethodDebug("ODLinkManager","GetLink");
  958.  
  959.     SOM_TRY
  960.  
  961.         ODPart* part = linkSpec->GetPart(ev);
  962.  
  963.         // If document has never been saved, refuse to create a link
  964.         DraftInfo* info = somSelf->GetDraftInfo(ev, part->GetStorageUnit(ev)->GetDraft(ev));
  965.         THROW_IF_NULL(info, kODErrDocNotSaved);
  966.  
  967.         TempODLink link = kODNULL;
  968.         TempODByteArrayStruct partData = linkSpec->GetPartData(ev);
  969.         ODVolatile(partData);
  970.  
  971.         TempODLinkSource linkSource = kODNULL;
  972.         ODVolatile(linkSource);
  973.  
  974.         linkSource = part->CreateLink(ev, (ODByteArray*) partData);
  975.         THROW_IF_NULL(linkSource, kODErrCannotCreateLink);
  976.         link = linkSource->GetLink(ev);
  977.         THROW_IF_NULL(link, kODErrCannotCreateLink);
  978.         link->Acquire(ev);
  979.     
  980.         ODLinkKey key;    ODVolatile(key);
  981.         if ( link->Lock(ev,0,&key) ) 
  982.         {
  983.             TRY
  984.                 if ( link->GetLinkEdition(ev, key, aliasData) )
  985.                 {
  986.                     // If a new cross-document destination is being created, and the edition
  987.                     // file is waiting for a save to update, force the edition file to update
  988.                     // now so the link content is the same as the content that would be pasted.
  989.                     // [cc; #1190727]
  990.                     DraftInfo* info = somSelf->GetDraftInfo(ev, link->GetStorageUnit(ev)->GetDraft(ev));
  991.                     if ( info && info->linksToExport->Contains(link) ) 
  992.                     {
  993.                         TRY
  994.                             link->UpdateLinkEdition(ev, key);
  995.                             info->linksToExport->RemoveAndRelease(link);
  996.                         CATCH_ALL
  997.                         ENDTRY
  998.                     }
  999.                 }
  1000.                 else
  1001.                 {
  1002.                     ODDraft* draft = part->GetStorageUnit(ev)->GetDraft(ev);
  1003.                     ODContainer* container = draft->GetDocument(ev)->GetContainer(ev);;
  1004.  
  1005.                     TempPlatformFile documentFile = GetPlatformFileFromContainer(ev, container);
  1006.                     ODFileSpec documentSpec = documentFile->GetFileSpec();
  1007.  
  1008.                     EditionContainerSpec editionContainer = NewEditionFile(ev, documentFile, draft);
  1009.  
  1010.                     link->CreateLinkEdition(ev,
  1011.                                             &editionContainer,
  1012.                                             &documentSpec,
  1013.                                             somSelf->NewSectionID(ev, draft),
  1014.                                             key,
  1015.                                             aliasData);
  1016.  
  1017.                     info->newExportedLinks->AddLastAndAcquire(link);
  1018.                 }
  1019.             CATCH_ALL
  1020.                 link->Unlock(ev, key);
  1021.                 RERAISE;
  1022.             ENDTRY
  1023.             link->Unlock(ev, key);
  1024.         }
  1025.             
  1026.     SOM_CATCH_ALL
  1027.     
  1028.     SOM_ENDTRY
  1029. }
  1030.  
  1031. //------------------------------------------------------------------------------
  1032. // UseLinkEdition
  1033. //------------------------------------------------------------------------------
  1034.  
  1035. SOM_Scope void SOMLINK ODLinkManagerUseLinkEdition(ODLinkManager *somSelf, Environment *ev,
  1036.         ODLinkSource* linkSource,
  1037.         ODByteArray* aliasData)
  1038. {
  1039.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  1040.     ODLinkManagerMethodDebug("ODLinkManager","UseLinkEdition");
  1041.  
  1042.     AliasHandle                aliasHandle;
  1043.     EditionContainerSpec    editionContainer;
  1044.     ODBoolean                wasChanged;
  1045.     OSErr                    error;
  1046.  
  1047.     SOM_TRY
  1048.         error = PtrToHand(aliasData->_buffer, (Handle*) &aliasHandle, aliasData->_length);
  1049.         THROW_IF_ERROR(error);
  1050.         TempODHandle editionAlias((ODHandle) aliasHandle);
  1051.  
  1052.         error = ResolveAlias(nil, aliasHandle, &editionContainer.theFile, &wasChanged);
  1053.         THROW_IF_ERROR(error);
  1054.     
  1055.         editionContainer.theFileScript = smSystemScript;
  1056.         editionContainer.thePart = kPartsNotUsed;
  1057.     
  1058.         ODDraft* draft = linkSource->GetStorageUnit(ev)->GetDraft(ev);
  1059.     
  1060.         ODContainer* container = draft->GetDocument(ev)->GetContainer(ev);;
  1061.         ODFileSpec documentSpec = GetODFileSpecFromContainer(ev, container);
  1062.     
  1063.         ODLinkKey key;    ODVolatile(key);
  1064.         if ( linkSource->Lock(ev,0,&key) ) 
  1065.         {
  1066.             TRY
  1067.                 linkSource->UseLinkEdition(ev,
  1068.                                     editionContainer, 
  1069.                                     &documentSpec,
  1070.                                     somSelf->NewSectionID(ev, draft),
  1071.                                     key);
  1072.             CATCH_ALL
  1073.                 linkSource->Unlock(ev, key);
  1074.                 RERAISE;
  1075.             ENDTRY
  1076.             linkSource->Unlock(ev, key);
  1077.         }
  1078.  
  1079.     SOM_CATCH_ALL
  1080.     
  1081.     SOM_ENDTRY
  1082. }
  1083.  
  1084. //------------------------------------------------------------------------------
  1085. // RequestLinkAEHandler
  1086. //------------------------------------------------------------------------------
  1087.  
  1088. ODStatic OSErr ODPascal RequestLinkAEHandler(
  1089.         const AppleEvent* requestLinkAppleEvent,
  1090.         AppleEvent* reply,
  1091.         long refCon)
  1092. {
  1093.     ODLinkManager*            somSelf = (ODLinkManager*) refCon;
  1094.     Environment*            ev = somGetGlobalEnvironment();
  1095.     AppleEvent                getLinkAppleEvent;
  1096.     AppleEvent                replyAppleEvent;
  1097.     AEAddressDesc            targetAddress;
  1098.     ProcessSerialNumber     psn;
  1099.     DescType                returnedType;
  1100.     Size                    actualSize;
  1101.     OSErr                    error;
  1102.     const long                kGetLinkReplyTimeout = 600;    // Ten seconds
  1103.     
  1104.     ODLinkSource*    linkSource = kODNULL;    ODVolatile(linkSource);
  1105.     ODLinkSpec*        linkSpec = kODNULL;        ODVolatile(linkSpec);
  1106.  
  1107.     TRY
  1108.     
  1109.         linkSpec = new ODLinkSpec;    // Can't use factory method; no draft object!
  1110.         THROW_IF_NULL(linkSpec, kODErrOutOfMemory);
  1111.  
  1112.         linkSpec->ReadFromAppleEvent(ev, (AppleEvent*) requestLinkAppleEvent);
  1113.  
  1114.         error = AEGetParamPtr(requestLinkAppleEvent, kODLinkSourceKey,
  1115.                                 typeLongInteger, &returnedType,
  1116.                                 &linkSource, sizeof(linkSource), &actualSize);
  1117.         THROW_IF_ERROR(error);
  1118.  
  1119.         // Create the GetLink event
  1120.         
  1121.         linkSpec->GetOriginatingProcessID(ev, &psn);
  1122.     
  1123.         error = AECreateDesc(typeProcessSerialNumber, &psn,
  1124.                             sizeof(ProcessSerialNumber), &targetAddress);
  1125.         THROW_IF_ERROR(error);
  1126.         TempAEDesc tmpTargetAddress(&targetAddress);
  1127.  
  1128.         error = AECreateAppleEvent(kODShellSignature, kODGetLinkEventID, 
  1129.                             &targetAddress, kAutoGenerateReturnID, 
  1130.                             kAnyTransactionID, &getLinkAppleEvent);
  1131.         THROW_IF_ERROR(error);
  1132.         TempAEDesc tmpGetLinkAppleEvent(&getLinkAppleEvent);
  1133.     
  1134.         linkSpec->WriteToAppleEvent(ev, &getLinkAppleEvent);
  1135.         
  1136.         error = AESend(&getLinkAppleEvent, &replyAppleEvent, 
  1137.                             kAEWaitReply | kAENeverInteract, kAENormalPriority,
  1138.                             kGetLinkReplyTimeout, NULL, NULL);
  1139.         TempAEDesc tmpReplyAppleEvent(&replyAppleEvent);
  1140.         THROW_IF_ERROR(error);
  1141.  
  1142.         // Process the reply
  1143.  
  1144.         TempODByteArray aliasData = ODAEGetByteArray(&replyAppleEvent, keyEditionAlias, typeAlias);
  1145.         somSelf->UseLinkEdition(ev, linkSource, aliasData);
  1146.         
  1147.     CATCH_ALL
  1148.     
  1149.         if ( linkSource )
  1150.         {
  1151.             linkSource->SetStatus(ev, kODErrCannotEstablishLink);
  1152.  
  1153.             // Ignore errors returned by UpdateDependents
  1154.             TRY
  1155.                 linkSource->GetLink(ev)->UpdateDependents(ev);
  1156.             CATCH_ALL
  1157.             ENDTRY
  1158.         }
  1159.  
  1160.     ENDTRY
  1161.  
  1162.     ODDeleteObject(linkSpec);
  1163.  
  1164.     return noErr;
  1165. }
  1166.  
  1167. //------------------------------------------------------------------------------
  1168. // SectionReadAEHandler
  1169. //------------------------------------------------------------------------------
  1170.  
  1171. ODStatic OSErr ODPascal SectionReadAEHandler(
  1172.         const AppleEvent* theAppleEvent,
  1173.         const AppleEvent* reply,
  1174.         long refCon)
  1175. {
  1176.     ODUnused(reply);
  1177.  
  1178.     ODLinkManager*        somSelf = (ODLinkManager*) refCon;
  1179.     ODLinkManagerData*    somThis = ODLinkManagerGetData(somSelf);
  1180.     Environment*        ev = somGetGlobalEnvironment ();
  1181.     SectionHandle        section = kODNULL;
  1182.     OSErr                error;
  1183.  
  1184.     error = GetSectionFromEvent(theAppleEvent, §ion);
  1185.  
  1186. #if ODDebug
  1187.         somPrintf("ODLinkManager: Section Read event received; section = %x, linkSource = %x\n",
  1188.                     section, (**section).refCon);
  1189. #endif
  1190.  
  1191.     if ( error == noErr )
  1192.     {
  1193.         if ( IsRegisteredSection(section) == noErr ) 
  1194.         {
  1195.             if ( _fRegisteredSections->Contains(section) )
  1196.             {
  1197.                 ODLinkSource* linkSource = (ODLinkSource*) (*section)->refCon;
  1198.                 ODLinkKey key;
  1199.  
  1200.                 if ( linkSource->Lock(ev,0,&key) ) 
  1201.                 {
  1202.                     TRY
  1203.                         linkSource->ReadLinkEdition(ev,key);
  1204.                         DraftInfo* info = somSelf->GetDraftInfo(ev, linkSource->GetStorageUnit(ev)->GetDraft(ev));
  1205.                         if ( info != (DraftInfo*) kODNULL ) 
  1206.                         {
  1207.                             info->linksImported = kODTrue;
  1208.                         }
  1209.                     CATCH_ALL
  1210.                         error = ErrorCode();
  1211.                     ENDTRY
  1212.                     linkSource->Unlock(ev, key);
  1213.                 }
  1214.             }
  1215.             else if ( _fChainedSectionReadAEHandler )
  1216.             {
  1217.                 error = CallAEEventHandlerProc(_fChainedSectionReadAEHandler, theAppleEvent, reply, _fChainedSectionReadRefcon);
  1218.             }
  1219.         }
  1220.     }
  1221.  
  1222.     return error;
  1223. }
  1224.  
  1225. //------------------------------------------------------------------------------
  1226. // SectionWriteAEHandler
  1227. //------------------------------------------------------------------------------
  1228.  
  1229. ODStatic OSErr ODPascal SectionWriteAEHandler(
  1230.         const AppleEvent* theAppleEvent,
  1231.         const AppleEvent* reply,
  1232.         long refCon)
  1233. {
  1234.     ODUnused(reply);
  1235.  
  1236.     ODLinkManager*        somSelf = (ODLinkManager*) refCon;
  1237.     ODLinkManagerData*    somThis = ODLinkManagerGetData(somSelf);
  1238.     Environment*        ev = somGetGlobalEnvironment ();
  1239.     ODLinkKey            key;
  1240.     SectionHandle        section = kODNULL;
  1241.     OSErr                error;
  1242.  
  1243.     error = GetSectionFromEvent(theAppleEvent, §ion);
  1244.  
  1245. #if ODDebug
  1246.         somPrintf("ODLinkManager: Section Write event received; section = %x, link = %x\n",
  1247.                     section, (**section).refCon);
  1248. #endif
  1249.  
  1250.     if ( error == noErr )
  1251.     {
  1252.         if ( IsRegisteredSection(section) == noErr ) 
  1253.         {
  1254.             if ( _fRegisteredSections->Contains(section) )
  1255.             {
  1256.                 ODLink* link = (ODLink*) (**section).refCon;
  1257.  
  1258.                 // Force ExportLinkEdition to write the edition file
  1259.                 (**section).mdDate = (TimeStamp) 0;
  1260.  
  1261.                 if ( link->Lock(ev,0,&key) ) 
  1262.                 {
  1263.                     TRY
  1264.                         link->UpdateLinkEdition(ev, key);
  1265.                     CATCH_ALL
  1266.                         error = ErrorCode();
  1267.                     ENDTRY
  1268.                     link->Unlock(ev, key);
  1269.                 }
  1270.             }
  1271.             else if ( _fChainedSectionWriteAEHandler )
  1272.             {
  1273.                 error = CallAEEventHandlerProc(_fChainedSectionWriteAEHandler, theAppleEvent, reply, _fChainedSectionWriteRefcon);
  1274.             }
  1275.         }
  1276.     }
  1277.  
  1278.     return error;
  1279. }
  1280.  
  1281. //------------------------------------------------------------------------------
  1282. // BuildErrorString
  1283. //------------------------------------------------------------------------------
  1284.  
  1285. ODStatic StringPtr BuildErrorString(ODSShort strResourceID, ODError error)
  1286. {
  1287.     Str63 numberString;
  1288.     Str255 msgStr;
  1289.  
  1290.     StringPtr result = kODNULL;
  1291.     
  1292.     ODSLong savedRefNum;
  1293.     BeginUsingLibraryResources(savedRefNum);
  1294.  
  1295.     NumToString(error, numberString);
  1296.     ReplaceIntoString(strResourceID, numberString, kODNULL, msgStr);
  1297.  
  1298.     if ( msgStr[0] > 0 )
  1299.     {
  1300.         ODULong ptrSize = msgStr[0]+1;
  1301.         result = (StringPtr) ODNewPtr(ptrSize);
  1302.         if ( result )
  1303.             ODBlockMove((ODPtr) &msgStr, (ODPtr) result, ptrSize);
  1304.     }
  1305.     
  1306.     EndUsingLibraryResources(savedRefNum);
  1307.     
  1308.     return result;
  1309. }
  1310.  
  1311. //------------------------------------------------------------------------------
  1312. // SectionScrollAEHandler
  1313. //------------------------------------------------------------------------------
  1314.  
  1315. ODStatic OSErr ODPascal SectionScrollAEHandler(
  1316.         const AppleEvent* theAppleEvent,
  1317.         const AppleEvent* reply,
  1318.         long refCon)
  1319. {
  1320.     ODUnused(reply);
  1321.  
  1322.     ODLinkManager*        somSelf = (ODLinkManager*) refCon;
  1323.     ODLinkManagerData*    somThis = ODLinkManagerGetData(somSelf);
  1324.     Environment*        ev = somGetGlobalEnvironment ();
  1325.     SectionHandle        section = kODNULL;
  1326.     OSErr                error;
  1327.  
  1328.     error = GetSectionFromEvent(theAppleEvent, §ion);
  1329.  
  1330. #if ODDebug
  1331.     somPrintf("ODLinkManager: Section Scroll event received; section = %x, link = %x\n",
  1332.                     section, (section ? (**section).refCon : 0));
  1333. #endif
  1334.  
  1335.     if ( error == noErr )
  1336.     {
  1337.         if ( IsRegisteredSection(section) == noErr ) 
  1338.         {
  1339.             if ( _fRegisteredSections->Contains(section) )
  1340.             {
  1341.                 TRY
  1342.                 ODLink* link = (ODLink*) (**section).refCon;
  1343.  
  1344.                 if ( link != kODNULL )
  1345.                 {
  1346.                     DraftInfo* info = somSelf->GetDraftInfo(ev, link->GetStorageUnit(ev)->GetDraft(ev));
  1347.                     if ( info && info->linksToDelete && info->linksToDelete->Contains(link) ) 
  1348.                         THROW(kODErrCannotRevealLink);
  1349.                     else
  1350.                         link->ShowSourceContent(ev);
  1351.                 }
  1352.                 CATCH_ALL
  1353.                     error = ErrorCode();
  1354.                                     
  1355.                     NMRemove(_fNMRecPtr);    // ensure not already queued
  1356.                     _fNMRecPtr->qType = nmType;
  1357.                     _fNMRecPtr->nmMark = 0;
  1358.                     _fNMRecPtr->nmIcon = nil;
  1359.                     _fNMRecPtr->nmSound = nil;
  1360.                     ODDisposePtr((ODPtr) _fNMRecPtr->nmStr);
  1361.                     _fNMRecPtr->nmStr = BuildErrorString(kODLinkMgrCannotShowSourceID, error);
  1362.                     _fNMRecPtr->nmResp = _fNMResponseUPP;
  1363.                     error = NMInstall(_fNMRecPtr);
  1364.                 ENDTRY
  1365.             }
  1366.             else if ( _fChainedSectionScrollAEHandler )
  1367.             {
  1368.                 error = CallAEEventHandlerProc(_fChainedSectionScrollAEHandler, theAppleEvent, reply, _fChainedSectionScrollRefcon);
  1369.             }
  1370.         }
  1371.     }
  1372.  
  1373.     return error;
  1374. }
  1375.  
  1376. //------------------------------------------------------------------------------
  1377. // NewEditionFile
  1378. //------------------------------------------------------------------------------
  1379.  
  1380. ODStatic EditionContainerSpec NewEditionFile(Environment* ev,
  1381.             PlatformFile* documentFile,
  1382.             ODDraft* draft)
  1383. {
  1384.     EditionContainerSpec    editionContainer;
  1385.     OSErr                    error;
  1386.     Str255                    documentName;
  1387.     ODFileSpec                documentSpec = documentFile->GetFileSpec();
  1388.  
  1389.     do {
  1390.         documentFile->GetAsciiName((char *) documentName, 254);
  1391.         CToPascalString((char *) documentName);
  1392.         EditionFileName(documentName, (ODUShort) NewEditionID(ev, draft));
  1393.         error = FSMakeFSSpec(documentSpec.vRefNum,
  1394.                              documentSpec.parID,
  1395.                              documentName,
  1396.                              &(editionContainer.theFile));
  1397.         }
  1398.     while (error == noErr);
  1399.  
  1400.     // Expect a file not found error
  1401.     if ( error != fnfErr )
  1402.         THROW_IF_ERROR(error);
  1403.  
  1404.     editionContainer.theFileScript = smSystemScript;
  1405.     editionContainer.thePart = kPartsNotUsed;
  1406.     
  1407.     return editionContainer;
  1408. }
  1409.  
  1410. //------------------------------------------------------------------------------
  1411. // GetSectionFromEvent
  1412. //------------------------------------------------------------------------------
  1413.  
  1414. ODStatic OSErr GetSectionFromEvent(const AppleEvent* theAppleEvent,
  1415.                 SectionHandle* section)
  1416. {
  1417.     DescType        returnedType;
  1418.     Size            actualSize;
  1419.     OSErr            error;
  1420.  
  1421.     error = AEGetParamPtr(theAppleEvent, keyDirectObject, typeSectionH, &returnedType,
  1422.                             section, sizeof(*section), &actualSize);
  1423. #if ODDebug
  1424.     if ( error != noErr )
  1425.         somPrintf("ODLinkManager: Error %d getting section from event\n", error);
  1426. #endif
  1427.  
  1428.     return error;
  1429. }
  1430.  
  1431. //------------------------------------------------------------------------------
  1432. // EditionFileName
  1433. //------------------------------------------------------------------------------
  1434.  
  1435. ODStatic void EditionFileName(Str255 fileName, ODUShort numb)
  1436. {
  1437.     Str63 numberString;
  1438.  
  1439.     NumToString(numb, numberString);
  1440.  
  1441.     TruncateFileName(fileName, numberString);
  1442.  
  1443.     ODSLong savedRefNum;
  1444.     BeginUsingLibraryResources(savedRefNum);
  1445.  
  1446.     ReplaceIntoString(kODLinkMgrEditionTemplateID, fileName, numberString, fileName);
  1447.  
  1448.     EndUsingLibraryResources(savedRefNum);
  1449. }
  1450.  
  1451. //------------------------------------------------------------------------------
  1452. // TruncateFileName
  1453. //------------------------------------------------------------------------------
  1454.  
  1455. ODStatic void TruncateFileName(Str255 fileName, Str63 numberString)
  1456. {
  1457.     const maxFileNameLength = 31;
  1458.  
  1459.     Str255 emptyString;
  1460.     emptyString[0] = (unsigned char) 0;
  1461.  
  1462.     ODSLong savedRefNum;
  1463.     BeginUsingLibraryResources(savedRefNum);
  1464.  
  1465.     ReplaceIntoString(kODLinkMgrEditionTemplateID, emptyString, numberString, emptyString);
  1466.     
  1467.     EndUsingLibraryResources(savedRefNum);
  1468.  
  1469.     if ( (StrLength(fileName)+StrLength(emptyString)) > maxFileNameLength )
  1470.         ClipStringToBytes( fileName,
  1471.                 maxFileNameLength-StrLength(emptyString), smCurrentScript );
  1472. }
  1473.  
  1474. //------------------------------------------------------------------------------
  1475. // NewEditionID
  1476. //------------------------------------------------------------------------------
  1477.  
  1478. ODStatic ODULong NewEditionID(Environment *ev, ODDraft* draft)
  1479. {
  1480.     return ReserveGlobalID(ev, draft, kODPropEditionID);
  1481. }
  1482.  
  1483. //------------------------------------------------------------------------------
  1484. // PeekNextGlobalID
  1485. //------------------------------------------------------------------------------
  1486.  
  1487. ODStatic ODULong PeekNextGlobalID(Environment *ev,
  1488.         ODDraft* draft,
  1489.         ODPropertyName globalProp)
  1490. {
  1491.     TempODStorageUnit    draftPropertiesSU = draft->AcquireDraftProperties(ev);
  1492.     ODULong            id = 0;
  1493.     
  1494.     if ( ODSUExistsThenFocus(ev, draftPropertiesSU, globalProp, kODULong) )
  1495.         StorageUnitGetValue(draftPropertiesSU, ev, sizeof(ODULong), (ODValue) &id);
  1496.  
  1497.     return ++id;
  1498. }
  1499.  
  1500. //------------------------------------------------------------------------------
  1501. // ReserveGlobalID
  1502. //------------------------------------------------------------------------------
  1503.  
  1504. ODStatic ODULong ReserveGlobalID(Environment *ev,
  1505.         ODDraft* draft,
  1506.         ODPropertyName globalProp)
  1507. {
  1508.     TempODStorageUnit    draftPropertiesSU = draft->AcquireDraftProperties(ev);
  1509.     ODULong            id = 0;
  1510.     
  1511.     ODSUForceFocus(ev, draftPropertiesSU, globalProp, kODULong);
  1512.     if ( draftPropertiesSU->GetSize(ev) > 0 )
  1513.         id = ODGetULongProp(ev, draftPropertiesSU, globalProp, kODULong);
  1514.     ++id;
  1515.     ODSetULongProp(ev, draftPropertiesSU, globalProp, kODULong, id);
  1516.     
  1517.     return id;
  1518. }
  1519.  
  1520. //------------------------------------------------------------------------------
  1521. // ODLinkManager::NewDraftInfo
  1522. //------------------------------------------------------------------------------
  1523.  
  1524. SOM_Scope void  SOMLINK ODLinkManagerNewDraftInfo(ODLinkManager *somSelf, Environment *ev,
  1525.         ODDraft* draft)
  1526. {
  1527.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  1528.     ODLinkManagerMethodDebug("ODLinkManager","NewDraftInfo");
  1529.  
  1530.     SOM_TRY
  1531.  
  1532.     // Create a new info structure for this draft
  1533.     DraftInfo* info = new DraftInfo;
  1534.  
  1535.     info->draft = draft;
  1536.     info->linksToExport = new ODRefCntCollection(ev);
  1537.     info->linksToDelete = new ODRefCntCollection(ev);
  1538.     info->newExportedLinks = new ODRefCntCollection(ev);
  1539.     info->linksImported = kODFalse;
  1540.     _fDraftInfos->AddLast(info);
  1541.  
  1542.     SOM_CATCH_ALL
  1543.     SOM_ENDTRY
  1544. }
  1545.  
  1546. //------------------------------------------------------------------------------
  1547. // ODLinkManager::GetDraftInfo
  1548. //------------------------------------------------------------------------------
  1549.  
  1550. SOM_Scope DraftInfo*  SOMLINK ODLinkManagerGetDraftInfo(ODLinkManager *somSelf, Environment *ev,
  1551.         ODDraft* draft)
  1552. {
  1553.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  1554.     ODLinkManagerMethodDebug("ODLinkManager","GetDraftInfo");
  1555.  
  1556.     OrderedCollectionIterator* iter = kODNULL; ODVolatile(iter);
  1557.     
  1558.     DraftInfo* result = (DraftInfo*) kODNULL;
  1559.     
  1560.     if ( draft && _fDraftInfos )
  1561.     {
  1562.         TRY
  1563.             iter = _fDraftInfos->CreateIterator();
  1564.  
  1565.             for (DraftInfo* info = (DraftInfo*) iter->First();
  1566.                     iter->IsNotComplete();
  1567.                     info = (DraftInfo*) iter->Next() )
  1568.             {
  1569.                 if ( info && draft->IsEqualTo(ev, info->draft) ) 
  1570.                 {
  1571.                     result = info;
  1572.                     break;
  1573.                 }
  1574.             }
  1575.         CATCH_ALL
  1576.         ENDTRY
  1577.  
  1578.         ODDeleteObject(iter);
  1579.     }
  1580.  
  1581.     return result;
  1582. }
  1583.  
  1584. //------------------------------------------------------------------------------
  1585. // ODLinkManager::somUninit
  1586. //------------------------------------------------------------------------------
  1587.  
  1588. SOM_Scope void  SOMLINK ODLinkManagersomUninit(ODLinkManager *somSelf)
  1589. {
  1590.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  1591.     ODLinkManagerMethodDebug("ODLinkManager","somUninit");
  1592.  
  1593.     // Note: It is incorrect to call methods on somSelf inside somUninit, as a 
  1594.     // subclass may have already been somUninited.  See OpenDoc Building Code for details.
  1595.     
  1596.     if (_fDraftInfos != (OrderedCollection*) kODNULL )
  1597.     {
  1598.         Environment* ev = somGetGlobalEnvironment();
  1599.         DraftInfo* info;
  1600.         while ((info = (DraftInfo*) _fDraftInfos->First()) != (DraftInfo*) kODNULL)
  1601.         {
  1602.             ODDeleteObject(info->linksToExport);
  1603.             ODDeleteObject(info->linksToDelete);
  1604.             ODDeleteObject(info->newExportedLinks);
  1605.             _fDraftInfos->RemoveFirst();
  1606.             delete info;
  1607.         }
  1608.         ODDeleteObject(_fDraftInfos);
  1609.     }
  1610.  
  1611.     ODDeleteObject(_fRegisteredSections);
  1612.  
  1613.     ODDeleteObject(_fSuspendedUpdateLinks);
  1614.  
  1615.     RemoveEventHandler(kODShellSignature, kODGetLinkEventID, (AEEventHandlerUPP) kODNULL, 0);
  1616.  
  1617.     RemoveEventHandler(kODShellSignature, kODRequestLinkEventID, (AEEventHandlerUPP) kODNULL, 0);
  1618.  
  1619.     RemoveEventHandler(sectionEventMsgClass, sectionReadMsgID, _fChainedSectionReadAEHandler, _fChainedSectionReadRefcon);
  1620.     _fChainedSectionReadAEHandler = kODNULL;
  1621.     
  1622.     RemoveEventHandler(sectionEventMsgClass, sectionWriteMsgID, _fChainedSectionWriteAEHandler, _fChainedSectionWriteRefcon);
  1623.     _fChainedSectionWriteAEHandler = kODNULL;
  1624.  
  1625.     RemoveEventHandler(sectionEventMsgClass, sectionScrollMsgID, _fChainedSectionScrollAEHandler, _fChainedSectionScrollRefcon);
  1626.     _fChainedSectionScrollAEHandler = kODNULL;
  1627.  
  1628.     if ( _fNMResponseUPP != kODNULL )
  1629.         DisposeRoutineDescriptor(_fNMResponseUPP);
  1630.  
  1631.     if ( _fNMRecPtr )
  1632.         ODDisposePtr((ODPtr) _fNMRecPtr->nmStr);
  1633.     ODDisposePtr(_fNMRecPtr);
  1634.  
  1635.     parent_somUninit(somSelf);
  1636. }
  1637.  
  1638. //------------------------------------------------------------------------------
  1639. // RemoveEventHandler
  1640. //------------------------------------------------------------------------------
  1641.  
  1642. ODStatic void RemoveEventHandler(AEEventClass theAEEventClass,
  1643.                                  AEEventID theAEEventID, 
  1644.                                  AEEventHandlerUPP chainedHandler, 
  1645.                                  long chainedRefcon)
  1646. {
  1647.     AEEventHandlerUPP    toBeDisposedUPP;
  1648.     long                toBeIgnoredRefCon;
  1649.  
  1650.     OSErr error = AEGetEventHandler(theAEEventClass, theAEEventID,
  1651.             &toBeDisposedUPP, &toBeIgnoredRefCon, kNotSysHandler);
  1652.     if ( error == noErr )
  1653.     {
  1654.         error = AERemoveEventHandler(theAEEventClass, theAEEventID,
  1655.                     toBeDisposedUPP,
  1656.                     kNotSysHandler);
  1657.         WASSERT(error==noErr);            
  1658.         DisposeRoutineDescriptor(toBeDisposedUPP);
  1659.         if ( chainedHandler )
  1660.         {
  1661.             error = AEInstallEventHandler(theAEEventClass, theAEEventID,
  1662.                 chainedHandler, chainedRefcon, kNotSysHandler);
  1663.             WASSERT(error==noErr);            
  1664.         }
  1665.     }
  1666. }
  1667.  
  1668. //------------------------------------------------------------------------------
  1669. // RegisterSubscribingLinks
  1670. //------------------------------------------------------------------------------
  1671.  
  1672. ODStatic void RegisterSubscribingLinks(Environment *ev, ODDraft* draft)
  1673. {
  1674.     // Internalize all link source objects; each link subscribing to an edition
  1675.     // file will register with the edition manager.
  1676.  
  1677.     ODLinkSourceIterator* iter;
  1678.  
  1679.     iter = draft->CreateLinkSourceIterator(ev);
  1680.  
  1681.     TRY{
  1682.         for (ODLinkSource* linkSource = iter->First(ev);
  1683.                 iter->IsNotComplete(ev);
  1684.                 linkSource = iter->Next(ev) )
  1685.         {
  1686.             linkSource->Release(ev);
  1687.         }
  1688.     }CATCH_ALL{
  1689.     }ENDTRY
  1690.  
  1691.     delete iter;
  1692. }
  1693.  
  1694. //------------------------------------------------------------------------------
  1695. // RegisterPublishingLinks
  1696. //------------------------------------------------------------------------------
  1697. ODStatic void RegisterPublishingLinks(Environment *ev, ODDraft* draft)
  1698. {
  1699.     // Internalize all link objects; each link publishing an edition file will 
  1700.     // register with the edition manager.
  1701.  
  1702.     ODLinkIterator* iter;
  1703.     
  1704.     iter = draft->CreateLinkIterator(ev);
  1705.  
  1706.     TRY{
  1707.         for (ODLink* link = iter->First(ev);
  1708.                 iter->IsNotComplete(ev);
  1709.                 link = iter->Next(ev) )
  1710.         {
  1711.             link->Release(ev);
  1712.         }
  1713.     }CATCH_ALL{
  1714.     }ENDTRY
  1715.  
  1716.     delete iter;
  1717. }
  1718.  
  1719. //------------------------------------------------------------------------------
  1720. // UpdateEditionFiles
  1721. //------------------------------------------------------------------------------
  1722.  
  1723. ODStatic void UpdateEditionFiles(Environment *ev, ODRefCntCollection* collection)
  1724. {
  1725.     if ( collection != kODNULL )
  1726.     {
  1727.         ODRefCntCollectionIterator iter(collection);
  1728.         ODLinkKey key;
  1729.     
  1730.         for (ODLink* link = (ODLink*) iter.First();
  1731.                 iter.IsNotComplete();
  1732.                 link = (ODLink*) iter.Next() )
  1733.         {
  1734.             if ( link->Lock(ev,0,&key) ) 
  1735.             {
  1736.                 TRY
  1737.                     link->UpdateLinkEdition(ev, key);
  1738.                 CATCH_ALL
  1739.                 ENDTRY
  1740.                 link->Unlock(ev, key);
  1741.             }
  1742.         }
  1743.     }
  1744. }
  1745.  
  1746. //------------------------------------------------------------------------------
  1747. // DeleteEditionFiles
  1748. //------------------------------------------------------------------------------
  1749.  
  1750. ODStatic void DeleteEditionFiles(Environment *ev, ODRefCntCollection* collection)
  1751. {
  1752.     if ( collection != kODNULL )
  1753.     {
  1754.         ODRefCntCollectionIterator iter(collection);
  1755.         ODLinkKey key;
  1756.     
  1757.         for (ODLink* link = (ODLink*) iter.First();
  1758.                 iter.IsNotComplete();
  1759.                 link = (ODLink*) iter.Next() )
  1760.         {
  1761.             if ( link->Lock(ev,0,&key) ) 
  1762.             {
  1763.                 TRY
  1764.                     link->DeleteLinkEdition(ev, key);
  1765.                 CATCH_ALL
  1766.                 ENDTRY
  1767.                 link->Unlock(ev, key);
  1768.             }
  1769.         }
  1770.     }
  1771. }
  1772.  
  1773. //------------------------------------------------------------------------------
  1774. // AppendULongToDraftProperty
  1775. //------------------------------------------------------------------------------
  1776.  
  1777. ODStatic void AppendULongToDraftProperty(Environment *ev,
  1778.     ODDraft* draft, ODPropertyName prop, ODULong value)
  1779. {
  1780.     TempODStorageUnit draftProperties = draft->AcquireDraftProperties(ev);
  1781.     ODSUForceFocus(ev, draftProperties, prop, kODULongSequence);
  1782.     draftProperties->SetOffset(ev, draftProperties->GetSize(ev));
  1783.     ODSetULongProp(ev, draftProperties, kODNULL, kODNULL, value);
  1784.     
  1785.     draft->SetChangedFromPrev(ev);
  1786. }
  1787.  
  1788. //------------------------------------------------------------------------------
  1789. // SectionIDReserved
  1790. //------------------------------------------------------------------------------
  1791.  
  1792. ODStatic ODBoolean SectionIDReserved(Environment *ev,
  1793.     ODDraft* draft, ODULong requestedID)
  1794. {
  1795.     ODBoolean result = kODFalse;
  1796.  
  1797.     TempODStorageUnit draftProperties = draft->AcquireDraftProperties(ev);
  1798.  
  1799.     if ( ODSUExistsThenFocus(ev, draftProperties, kODPropReservedSectionIDs, kODULongSequence) )
  1800.     {
  1801.         ODULong size = draftProperties->GetSize(ev);
  1802.         while ( draftProperties->GetOffset(ev) < size )
  1803.         {
  1804.             if ( ODGetULongProp(ev, draftProperties, kODNULL, kODNULL) == requestedID )
  1805.             {
  1806.                 result = kODTrue;
  1807.                 break;
  1808.             }
  1809.         }
  1810.     }
  1811.  
  1812.     return result;
  1813. }
  1814.